#include "memobj.h"

#include "types.h"

namespace Arm {
    Register::Register(int id) : id(id) {
        if (id & 128)
            type = Type::Basic::Float;
        else
            type = Type::Basic::Int;
    }
    Register::Register(Type::Basic type, int id) : type(type), id(id) {}
    void Register::GenAsm(std::ostream& os) const {
        if (id & 128)
            os << "s" << (id ^ 128);
        else {
            if (id == 15)
                os << "pc";
            else if (id == 14)
                os << "lr";
            else if (id == 13)
                os << "sp";
            else
                os << "r" << id;
        }
    }

    void GlobalVar::GenAsm(std::ostream& os) const {
        os << name << ":\n";
        int maxpos = 0;
        for (auto [pos, v] : *init) maxpos = std::max(maxpos, pos + 1);
        for (int i = 0; i < maxpos; ++i) {
            int val = 0;
            if (init->count(i)) val = (*init)[i];
            os << "    .long " << val << "\n";
        }
        if (maxpos < size) {
            os << "    .zero " << 4 * (size - maxpos) << "\n";
        }
    }

    ImmOffset::ImmOffset(Register base, int offset)
        : base(base), offset(offset) {}
    void ImmOffset::GenAsm(std::ostream& os) const {
        os << "[", base.GenAsm(os);
        if (offset != 0) os << ", #" << offset;
        os << "]";
    }

    RegOffset::RegOffset(Register base, Register offset, int lshift)
        : base(base), offset(offset), lshift(lshift) {}
    void RegOffset::GenAsm(std::ostream& os) const {
        os << "[", base.GenAsm(os);
        os << ", ", offset.GenAsm(os);
        if (lshift != 0) os << ", lsl #" << lshift;
        os << "]";
    }

    void Immediate::GenAsm(std::ostream& os) const {
        os << "#";
        if (value.type == Type::Basic::Int)
            os << value.v.i;
        else
            os << value.v.f;
    }

}  // namespace Arm
